/*
 * The MIT License
 *
 * Copyright (c) 2010, Bharathwaaj Srinivasan, bluegenetic@gmail.com, bharathwaaj.s@gmail.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef CURLTWEET_API_H
#define CURLTWEET_API_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "curltweet_types.h"
#include "curltweet_common.h"
#include "ezxml.h"

#define CURLTWEET_MAX_MESSAGE_SIZE  140
#define CURLTWEET_MAX_USERNAME_SIZE 15
#define CURLTWEET_MAX_FULLNAME_SIZE 20
#define CURLTWEET_MAX_LISTNAME_SIZE 25
#define CURLTWEET_MAX_PASSWORD_SIZE 128

/* Warning:
 * CURLTWEET_MAX_URL_LENGTH is subject to stack size. Maintain a smaller value. Else we might stack overflow!!
 */
#define CURLTWEET_MAX_URL_LENGTH 256

#define CURLTWEET_PUBLIC_TIMELINE_URL               "http://twitter.com/statuses/public_timeline.xml"
#define CURLTWEET_HOME_TIMELINE_URL                 "http://twitter.com/statuses/home_timeline.xml"
#define CURLTWEET_FRIENDS_TIMELINE_URL              "http://twitter.com/statuses/friends_timeline.xml"
#define CURLTWEET_USER_TIMELINE_URL                 "http://twitter.com/statuses/user_timeline.xml"
#define CURLTWEET_MENTIONS_TIMELINE_URL             "http://twitter.com/statuses/mentions.xml"
#define CURLTWEET_RETWEETED_BY_ME_TIMELINE_URL      "http://api.twitter.com/1/statuses/retweeted_by_me.xml"
#define CURLTWEET_RETWEETED_TO_ME_TIMELINE_URL      "http://api.twitter.com/1/statuses/retweeted_to_me.xml"
#define CURLTWEET_RETWEETS_OF_ME_TIMELINE_URL       "http://api.twitter.com/1/statuses/retweets_of_me.xml"

#define CURLTWEET_STATUS_SHOW_URL                   "http://twitter.com/statuses/show/"
#define CURLTWEET_STATUS_UPDATE_URL                 "http://twitter.com/statuses/update.xml"
#define CURLTWEET_STATUS_DESTROY_URL                "http://twitter.com/statuses/destroy/"
#define CURLTWEET_STATUS_RETWEET_URL                "http://api.twitter.com/1/statuses/retweet/"
#define CURLTWEET_STATUS_RETWEETS_URL               "http://api.twitter.com/1/statuses/retweets/"

/**
 * \enum    CtError
 * \brief   Error Return Values from curl tweet apis
 */
typedef enum CtErrorTag
{
    ERR_NONE           = 0,
    ERR_INTERNAL       = 1,
    ERR_MEMORY_ALLOC   = 2,
    ERR_RESOURCE_ALLOC = 3,
    ERR_INVALID_PARAM  = 4,
} CtError;

/**
 * \enum    UrlFormat
 * \brief   Different Data Formats
 */
typedef enum UrlFormatTag
{
    URL_FORMAT_XML   = 0,
    URL_FORMAT_JSON  = 1,
    URL_FORMAT_RSS   = 2,
    URL_FORMAT_ATOM  = 3
} UrlFormat;

typedef enum Timeline
{
    TIMELINE_PUBLIC,
    TIMELINE_HOME,
    TIMELINE_FRIENDS,
    TIMELINE_USER,
    TIMELINE_MENTIONS,
    TIMELINE_RETWEETED_BY_ME,
    TIMELINE_RETWEETED_TO_ME,
    TIMELINE_RETWEETS_OF_ME
} Timeline;

typedef enum StatusOptTag
{
    STATUS_SHOW,
    STATUS_UPDATE,
    STATUS_DESTROY,
    STATUS_RETWEET,
    STATUS_RETWEETS
} StatusOpt;

typedef struct CtStringTag
{
    uint8_t *p_u8_string;
    uint32_t u32_stringLen;
} CtString;

typedef struct UserInfoTag
{
    bool_t     eb_contribEnabled;                                  /* contributors_enabled */
    bool_t     eb_protected;                                       /* protected */
    bool_t     eb_bgTile;                                          /* profile_background_tile */
    bool_t     eb_notifications;                                   /* notifications  */
    bool_t     eb_geoEnabled;                                      /* */
    bool_t     eb_verified;                                        /* verified */
    bool_t     eb_following;                                       /* following */
    int32_t    s32_utcOffset;                                      /* utc_offset */
    uint32_t   u32_numFollowers;                                   /* followers_count */
    uint32_t   u32_numFriends;                                     /* friends_count */
    uint32_t   u32_numFavourites;                                /* favourites_count */
    uint32_t   u32_numOfStatuses;                                  /* statuses_count */
    uint64_t   u64_userId;                                         /* id - User Id */
    uint8_t    *p_u8_username;                                     /* name - Screen Name */
    uint8_t    *p_u8_fullname;                                     /* name - Full Name */
    uint8_t    *p_u8_location;                           /* location */
    uint8_t    *p_u8_description;                        /* description */
    uint8_t    *p_u8_profImgUrl;                         /* profile_image_url */
    uint8_t    *p_u8_userUrl;                            /* url */
    uint8_t    *p_u8_profBgColor;                                    /* profile_background_color */
    uint8_t    *p_u8_profTextColor;                                  /* profile_text_color */
    uint8_t    *p_u8_profLinkColor;                                  /* profile_link_color */
    uint8_t    *p_u8_sideBarFillColor;                               /* profile_sidebar_fill_color */
    uint8_t    *p_u8_sideBarBorderColor;                             /* profile_sidebar_border_color */
    uint8_t    *p_u8_profCreationTime;                   /* created_at */
    uint8_t    *p_u8_timeZone;                           /* time_zone */
    uint8_t    *p_u8_bgImageUrl;                         /* profile_background_image_url */
    uint8_t    *p_u8_lang;                               /* lang */
} UserInfo;

/* TODO Geo-tagging, contributers support not added */
typedef struct StatusTag
{
    bool_t     eb_truncated;                                       /* Truncated */
    bool_t     eb_favorited;                                       /* favorited */
    uint64_t   u64_replyToStatusId;                                /* in_reply_to_status_id */
    uint64_t   u64_replyToUserId;                                  /* in_reply_to_user_id   */
    uint64_t   u64_statusId;                                       /* Status identification - id */
    uint8_t    *p_u8_postTime;                           /* created_at */
    uint8_t    *p_u8_srcUrl;                             /* source */
    uint8_t    *p_u8_srcName;                            /* source */
    uint8_t    *p_u8_imageUrl;                           /* */
    uint8_t    *p_u8_replyToUsername;  /* in_reply_to_screen_name */
    uint8_t    *p_u8_tweet;             /* text Message Text aka tweet */
    UserInfo  s_userInfo;
} Status;

typedef struct StatusesTag
{
    uint32_t u32_numOfStatuses;
    Status *p_s_statusesArr;
} StatusRoot;

typedef struct ListTag
{
    bool_t     eb_isPrivate;
    uint8_t    a_u8_listName[CURLTWEET_MAX_LISTNAME_SIZE];       /* name - list name */
    uint32_t   u32_numOfSubscribers;
    uint32_t   u32_numOfMembers;
    uint64_t   u64_listId;                                       /* List identification - id */
    uint8_t    *p_u8_fullListName;
    uint8_t    *p_u8_slug;
    uint8_t    *p_u8_description;
    uint8_t    *p_u8_listUri;
    UserInfo   *p_s_userInfo;
} List;

typedef struct ListsTag
{
    uint32_t   u32_numOfLists;
    uint64_t   u64_prevCursor;                                     /* */
    uint64_t   u64_nextCursor;                                     /* */
    Status *p_s_publicListsArr;
} ListRoot;

typedef struct TimelineParamsTag
{
    int32_t     s32_count;
    int32_t     s32_page;
    uint64_t    u64_sinceId;
    uint64_t    u64_maxId;
    uint64_t    u64_userId;
    uint8_t     a_u8_username[CURLTWEET_MAX_USERNAME_SIZE];
} TimelineParams;

typedef struct StatusParamsTag
{
    uint64_t u64_statusId;
    uint8_t a_u8_tweet[CURLTWEET_MAX_MESSAGE_SIZE];
    float f32_latitude;
    float f32_longitude;
    uint32_t u32_count;
} StatusParams;

struct CurlTweetTag;
typedef struct CurlTweetTag *CurlTweet;


CtError curltweet_init (void);

CtError curltweet_cleanup (void);

CtError curltweet_alloc (CurlTweet *pp_s_ctHandle);

CtError curltweet_free (CurlTweet p_s_ctHandle);

CtError curltweet_freeStatuses (CurlTweet p_s_ctHandle, StatusRoot *p_s_statuses);

/* All apis should be followed by curltweet_freeStatuses to avoid memory leaks */

/* Following apis require user to be logged in */
CtError curltweet_logIn (CurlTweet p_s_ctHandle , CtString *p_u8_userName, CtString *p_u8_password);

CtError curltweet_logOut (CurlTweet p_s_ctHandle);

CtError curltweet_getTimeline (CurlTweet p_s_ctHandle,
                               Timeline e_timeline,
                               TimelineParams *p_s_optional,
                               StatusRoot *p_s_statuses);

/* Status Methods */
/* Authentication required if author of status is protected, else not required */
CtError curltweet_getStatus (CurlTweet p_s_ctHandle,
                                            StatusRoot *p_s_statuses,
                                            uint64_t u64_statusId);

/* Authentication required */
CtError curltweet_updateStatus (CurlTweet p_s_ctHandle,
                                               uint64_t u64_replyToStatusId,
                                               CtString *p_u8_tweet,
                                               float f32_latitude,
                                               float f32_longitude,
                                               StatusRoot *p_s_statuses);

/* Authentication required */
CtError curltweet_deleteStatus (CurlTweet p_s_ctHandle,
                                               uint64_t u64_statusId);

/* Authentication required */
CtError curltweet_retweetStatus (CurlTweet p_s_ctHandle,
                                                uint64_t u64_statusId);

/* Authentication required */
CtError curltweet_getTweetRetweets (CurlTweet p_s_ctHandle,
                                                   uint64_t u64_statusId,
                                                   uint32_t *p_u32_count);
/* Authentication not required */
CtError curltweet_getUserInfo (CurlTweet p_s_ctHandle,
                                              StatusRoot *p_s_statuses,
                                              uint64_t *p_u64_userId,
                                              CtString *p_s_userName);

/* Authentication required */
CtError curltweet_userSearch (CurlTweet p_s_ctHandle,
                                             StatusRoot *p_s_statuses,
                                             CtString *p_u8_query,
                                             uint32_t *p_u32_numOfStatuses,
                                             uint32_t *p_u32_pageNo);

/* Authentication required if user is protected, else not required */
/* TODO Update structure for cursor */
CtError curltweet_friendsInfo (CurlTweet p_s_ctHandle,
                                              StatusRoot *p_s_statuses,
                                              uint64_t *p_u64_userId,
                                              CtString *p_s_userName,
                                              int64_t *p_s64_cursor);

/* Authentication required if user is protected, else not required */
/* TODO Update structure for cursor */
CtError curltweet_followersInfo (CurlTweet p_s_ctHandle,
                                                StatusRoot *p_s_statuses,
                                                uint64_t *p_u64_userId,
                                                CtString *p_s_userName,
                                                int64_t *p_s64_cursor);

/* POST LISTS */
/* Authentication required */
CtError curltweet_createNewList (CurlTweet p_s_ctHandle,
                                                CtString *p_s_listName,
                                                bool_t eb_isPrivate,
                                                CtString *p_s_description);

/* Authentication required */
CtError curltweet_updateListInfo (CurlTweet p_s_ctHandle,
                                                 CtString *p_s_listName,
                                                 bool_t eb_isPrivate,
                                                 CtString *p_s_description);

/* Authentication required */
/* TODO List structure to be abstracted
 * FIXME Abstract list structure
 */
CtError curltweet_getLists (CurlTweet p_s_ctHandle,
                                           CtString *p_s_userName,
                                           int64_t *p_s64_cursor,
                                           ListRoot *p_s_lists);

/* Authentication required */
/* TODO List structure to be abstracted
 * FIXME Abstract list structure
 */
CtError curltweet_showList (CurlTweet p_s_ctHandle,
                                           uint64_t u64_listId,
                                           List *p_s_listInfo);

/* Authentication required */
CtError curltweet_deleteList (CurlTweet p_s_ctHandle,
                                             uint64_t u64_listId);

/* Authentication required */
CtError curltweet_getListStatuses (CurlTweet p_s_ctHandle,
                                                  uint64_t u64_listId,
                                                  TimelineParams *p_s_optional,
                                                  StatusRoot *p_s_statuses);

/* Authentication required */
CtError curltweet_getListMemberShips (CurlTweet p_s_ctHandle,
                                                     ListRoot *p_s_lists,
                                                     int64_t *p_s64_cursor);

/* Authentication required */
CtError curltweet_getListSubscriptions (CurlTweet p_s_ctHandle,
                                                     ListRoot *p_s_lists,
                                                     int64_t *p_s64_cursor);

/* Authentication required */
CtError curltweet_getListMembers (CurlTweet p_s_ctHandle,
                                                 uint64_t u64_listId,
                                                 int64_t *p_s64_cursor,
                                                 StatusRoot *p_s_statuses);

/* Authentication required */
CtError curltweet_addMemberToList (CurlTweet p_s_ctHandle,
                                                  uint64_t u64_listId,
                                                  uint64_t u64_userId);

/* Authentication required */
CtError curltweet_deleteMemberFromList (CurlTweet p_s_ctHandle,
                                                       uint64_t u64_listId,
                                                       uint64_t u64_userId);

/* Authentication required */
CtError curltweet_checkMemberFromList (CurlTweet p_s_ctHandle,
                                                       uint64_t u64_listId,
                                                       uint64_t u64_userId,
                                                       bool_t *p_eb_present);

/* List Subscribing Options */
/* Authentication required */
CtError curltweet_getListSubscribers (CurlTweet p_s_ctHandle,
                                                     uint64_t u64_listId,
                                                     int64_t *p_s64_cursor,
                                                     StatusRoot *p_s_statuses);

/* Authentication required */
CtError curltweet_followList (CurlTweet p_s_ctHandle,
                                             uint64_t u64_listId);

/* Authentication required */
CtError curltweet_unsubscribeFromList (CurlTweet p_s_ctHandle,
                                                      uint64_t u64_listId,
                                                      uint64_t u64_userId);

/* Authentication required */
#if 0
CtError curltweet_checkUserSubscriptionInList (CurlTweet p_s_ctHandle,
                                                              uint64_t u64_)
#endif
#ifdef __cplusplus
}
#endif

#endif /* CURLTWEET_API_H ENDS HERE */
